package com.pcitc.paas.feign.demo.consumer.server.config;

import com.netflix.hystrix.HystrixCommand;
import com.pcitc.paas.feign.demo.api.processor.RequestObjectParameterProcessor;
import com.pcitc.paas.feign.demo.api.processor.RequestObjectQueryMapEncoder;
import feign.Contract;
import feign.Feign;
import feign.codec.Encoder;
import feign.hystrix.HystrixFeign;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
import org.springframework.cloud.openfeign.annotation.PathVariableParameterProcessor;
import org.springframework.cloud.openfeign.annotation.RequestHeaderParameterProcessor;
import org.springframework.cloud.openfeign.annotation.RequestParamParameterProcessor;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.core.convert.ConversionService;

import java.util.ArrayList;
import java.util.List;

/**
 * description: <br>
 * createTime: 2021/6/21 17:59 <br>
 *
 * @author zzh
 */
@Configuration
@ConditionalOnClass({Feign.class})
public class FeignConfiguration {
    private static final Logger log = LoggerFactory.getLogger(FeignConfiguration.class);

    public FeignConfiguration() {
    }

    @Bean
    @Primary
    @Scope("prototype")
    public Encoder multipartFormEncoder(@Autowired ObjectFactory<HttpMessageConverters> messageConverters) {
        return new FeignSpringFormEncoder(new SpringEncoder(messageConverters));
    }

    @Bean
    public Contract feignContract(ConversionService feignConversionService) {
        List<AnnotatedParameterProcessor> annotatedArgumentResolvers = new ArrayList();
        annotatedArgumentResolvers.add(new PathVariableParameterProcessor());
        annotatedArgumentResolvers.add(new RequestParamParameterProcessor());
        annotatedArgumentResolvers.add(new RequestHeaderParameterProcessor());
        annotatedArgumentResolvers.add(new RequestObjectParameterProcessor());
        return new SpringMvcContract(annotatedArgumentResolvers, feignConversionService);
    }

    @Configuration
    @ConditionalOnClass({HystrixCommand.class, HystrixFeign.class})
    protected static class HystrixFeignConfiguration {
        protected HystrixFeignConfiguration() {
        }

        @Bean
        @Scope("prototype")
        @ConditionalOnProperty(
                name = {"feign.hystrix.enabled"}
        )
        public Feign.Builder feignHystrixBuilder() {
            feign.hystrix.HystrixFeign.Builder builder = HystrixFeign.builder();
            builder.queryMapEncoder(new RequestObjectQueryMapEncoder());
            return builder;
        }
    }
}
